/*
 * @Author: 0x9DEFA478
 * @Date: 2021-08-30 17:16:51
 * @LastEditTime: 2021-09-13 20:59:54
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "H_AudioResample.h"
#include "math.h"


//获取音量倍数
static H_AudioResample_FloatType GetVol(int Vol_i){
  
  if(Vol_i==100){
    return cH_AudioResample_FloatConst(1.0);
  }

	return powf(cH_AudioResample_FloatConst(10.0),((H_AudioResample_FloatType)(Vol_i-100))/cH_AudioResample_FloatConst(20.0)*cH_AudioResample_FloatConst(0.72));
}

/**
 * @brief 获取音量倍数
 * @param Vol_i 0~100的音量值
 * @return noEdit
 */
H_AudioResample_FloatType H_AudioResample_GetMultiple(int Vol_i){
  return GetVol(Vol_i);
}

/**
 * @brief 初始化H_AudioResample
 * @param ar H_AudioResample对象
 * @param OutputBuffer 输出缓冲区 要确保(OutputBufferBlockAllCount*SizeOfPerOutput)要小于OutputBuffer的大小
 * @param OutputBufferBlockAllCount //缓冲块数量 多个缓存块连续分布在OutputBuffer
 * @param SizeOfPerOutput 每个输出包长度 需要保证这个为2的倍数 单位:sizeof(H_AudioResample_IntegerType)字节
 * @param InputBuffer 输入缓冲区 这个缓存负责将零碎的音频数据组成一个连续的数组 要确保SizeOfPerInput要小于InputBuffer的大小
 * @param SizeOfPerInput InputBuffer使用的长度 需要保证这个为2的倍数 单位:sizeof(H_AudioResample_FloatType)字节
 * @return 无
 */
void H_AudioResample_Init(H_AudioResample* ar
  ,H_AudioResample_IntegerType* OutputBuffer,int OutputBufferBlockAllCount,int SizeOfPerOutput
  ,H_AudioResample_FloatType* InputBuffer,int SizeOfPerInput){

  ar->IsSuspend=-1;

  ar->Volume.ChannelMode=vH_AudioResample_Volume_ChannelMode_Stereo;
  ar->Volume.Channelx_AmplitudeMultiple[0]=GetVol(67);
  ar->Volume.Channelx_AmplitudeMultiple[1]=GetVol(67);

  ar->ResampleCtrl.Status=vH_AudioResample_ResampleCtrl_Status_SpeedDefault;
  ar->ResampleCtrl.IsDefaultSpeed=0;

  ar->Input.Buffer=InputBuffer;
  ar->Input.SizeOfPerInput=SizeOfPerInput;

  ar->Output.Buffer=OutputBuffer;
  ar->Output.OutputBufferBlockAllCount=OutputBufferBlockAllCount;
  ar->Output.OutputBufferBlockMaxCount=OutputBufferBlockAllCount-1;
  ar->Output.SizeOfPerOutput=SizeOfPerOutput;
  ar->Output.OccupyCount=0;

  ar->Process=NULL;

}

/**
 * @brief 设置最容纳数量 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param OutputBufferBlockMaxCount 最大容纳数量 不能超过(OutputBufferBlockAllCount-1)
 * @return 无
 */
void H_AudioResample_SetOutputBufferBlockMaxCount(H_AudioResample* ar,int OutputBufferBlockMaxCount){
  
  if(ar->IsSuspend==0){
    return;
  }

  if(OutputBufferBlockMaxCount>(ar->Output.OutputBufferBlockAllCount-1)){
    return;
  }

  ar->Output.OutputBufferBlockMaxCount=OutputBufferBlockMaxCount;
}

/**
 * @brief 设置重采样相关参数 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param SRC_Ratio 速率有偏差时附加的重采样倍数 为0~1之间的值
 * @param Threshold_SpeedDown 输出缓冲区超过这个阈值时 减少输出样本的数量
 * @param Threshold_SpeedUpStop 输出缓冲区超过这个阈值时 如果处于 增加输出样本 状态, 则恢复默认速度状态
 * @param Threshold_SpeedDownStop 输出缓冲区低于这个阈值时 如果处于 减少输出样本 状态, 则恢复默认速度状态
 * @param Threshold_SpeedUp 输出缓冲区低于这个阈值时 增加输出样本的数量
 * @return 无
 */
void H_AudioResample_SetResample(H_AudioResample* ar,H_AudioResample_FloatType SRC_Ratio,int Threshold_SpeedDown,int Threshold_SpeedUpStop,int Threshold_SpeedDownStop,int Threshold_SpeedUp){

  if(ar->IsSuspend==0){
    return;
  }

  ar->ResampleCtrl.SRC_Ratio=SRC_Ratio;
  ar->ResampleCtrl.Threshold_SpeedDown=Threshold_SpeedDown;
  ar->ResampleCtrl.Threshold_SpeedUpStop=Threshold_SpeedUpStop;
  ar->ResampleCtrl.Threshold_SpeedDownStop=Threshold_SpeedDownStop;
  ar->ResampleCtrl.Threshold_SpeedUp=Threshold_SpeedUp;

}

/**
 * @brief 设置输出包大小 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param SizeOfPerOutput 每个输出包长度 单位:sizeof(H_AudioResample_IntegerType)字节
 * @return 无
 */
void H_AudioResample_SetSizeOfPerOutput(H_AudioResample* ar,int SizeOfPerOutput){
  if(ar->IsSuspend==0){
    return;
  }
  ar->Output.SizeOfPerOutput=SizeOfPerOutput;
}

/**
 * @brief 设置输入缓存使用大小 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param SizeOfPerInput 每个输出包长度 单位:sizeof(H_AudioResample_FloatType)字节
 * @return 无
 */
void H_AudioResample_SetSizeOfPerInput(H_AudioResample* ar,int SizeOfPerInput){
  if(ar->IsSuspend==0){
    return;
  }
  ar->Input.SizeOfPerInput=SizeOfPerInput;
}

/**
 * @brief 设置H_AudioResample状态
 * @param IsSuspend 0:正常工作 其他:挂起
 * @return 无
 */
void H_AudioResample_SetSuspend(H_AudioResample* ar,int IsSuspend){
  int i;
  if((ar->IsSuspend!=0)&&(IsSuspend==0)){
    //从挂起转为正常

    //缓存恢复为初时状态

    ar->ResampleCtrl.Status=vH_AudioResample_ResampleCtrl_Status_SpeedDefault;

    ar->Input.LastInputLength=ar->Input.SizeOfPerInput;
    ar->Input.Buffer_WritePtr=ar->Input.Buffer;

    ar->Output.I=0;
    ar->Output.O=0;
    ar->Output.I_Block=0;

    for(i=0;i<8;i++){
      ar->LastData[i]=cH_AudioResample_FloatConst(0.0);
    }

  }
  ar->IsSuspend=IsSuspend;
}

/**
 * @brief 设置声道模式
 * @param ar H_AudioResample对象
 * @param ChannelMode 声道模式 vH_AudioResample_Volume_ChannelMode_Stereo
 *                            vH_AudioResample_Volume_ChannelMode_ChannelL
 *                            vH_AudioResample_Volume_ChannelMode_ChannelR
 *                            vH_AudioResample_Volume_ChannelMode_ChannelSwap
 * @return 无
 */
void H_AudioResample_SetChannelMode(H_AudioResample* ar,int ChannelMode){
  ar->Volume.ChannelMode=ChannelMode;
}

/**
 * @brief 设置音量
 * @param ar H_AudioResample对象
 * @param MasterVolume 主音量 (0~100)
 * @param Volumes 各个声道音量 (0~100)
 * @return 无
 */
void H_AudioResample_SetVolume(H_AudioResample* ar,int MasterVolume,int* Volumes){

  H_AudioResample_FloatType v;

  v=GetVol(MasterVolume);

  ar->Volume.Channelx_AmplitudeMultiple[0]=v*GetVol(Volumes[0]);
  ar->Volume.Channelx_AmplitudeMultiple[1]=v*GetVol(Volumes[1]);

}

/**
 * @brief 设置音量倍数
 * @param ar H_AudioResample对象
 * @param MasterMultiple 主音量 (0~1)
 * @param VolumeMultiples 各个声道音量 (0~1)
 * @return 无
 */
void H_AudioResample_SetVolumeMultiple(H_AudioResample* ar,H_AudioResample_FloatType MasterMultiple,H_AudioResample_FloatType* VolumeMultiples){

  ar->Volume.Channelx_AmplitudeMultiple[0]=MasterMultiple*VolumeMultiples[0];
  ar->Volume.Channelx_AmplitudeMultiple[1]=MasterMultiple*VolumeMultiples[1];

}

/**
 * @brief 设置是否固定默认速度
 * @param ar H_AudioResample对象
 * @param IsDefaultSpeed 如果为0 则启用速度校正 否则不进行速度校正 原速输出
 * @return 无
 */
void H_AudioResample_SetIsDefaultSpeed(H_AudioResample* ar,int IsDefaultSpeed){

  ar->ResampleCtrl.IsDefaultSpeed=IsDefaultSpeed;
}




/**
 * @brief 初始化一个额外进程句柄
 * @param ExtProcess 要初始化的句柄对象
 * @param Process 进程回调
 * @param v Process调用时传入的参数
 * @return 无
 */
void H_AudioResample_ExtProcess_Init(H_AudioResample_ExtProcess* ExtProcess,void (*Process)(void*,H_AudioResample_FloatType*,int),void* v){

  ExtProcess->Next=NULL;
  ExtProcess->Last=NULL;
  ExtProcess->v=v;
  ExtProcess->Process=Process;
}

/**
 * @brief 添加进程到ar 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param refExtProcess 参考对象(该对象需在ar中) 添加到改对象的后一个 如果为NULL 则添加到头部
 * @param ExtProcess 要添加的进程对象
 * @return 无
 */
void H_AudioResample_AddExtProcess(H_AudioResample* ar,H_AudioResample_ExtProcess* refExtProcess,H_AudioResample_ExtProcess* ExtProcess){
  H_AudioResample_ExtProcess* p;
  
  if(ar->IsSuspend==0){
    return;
  }

  if(refExtProcess==NULL){
    p=ar->Process;

    ExtProcess->Last=NULL;
    ExtProcess->Next=p;

    if(p!=NULL){
      p->Last=ExtProcess;
    }

    ar->Process=ExtProcess;

  }else{
    p=refExtProcess->Next;

    ExtProcess->Last=refExtProcess;
    ExtProcess->Next=p;

    if(p!=NULL){
      p->Last=ExtProcess;
    }

    refExtProcess->Next=ExtProcess;

  }

}

/**
 * @brief 从ar中移除ExtProcess 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param ExtProcess 要移除的进程对象
 * @return 无
 */
void H_AudioResample_RemoveExtProcess(H_AudioResample* ar,H_AudioResample_ExtProcess* ExtProcess){
  H_AudioResample_ExtProcess* p_last;
  H_AudioResample_ExtProcess* p_next;
  
  if(ar->IsSuspend==0){
    return;
  }

  p_last=ExtProcess->Last;
  p_next=ExtProcess->Next;

  if(p_last==NULL){

    ar->Process=p_next;
    if(p_next!=NULL){
      p_next->Last=NULL;
    }

  }else{

    p_last->Next=p_next;
    if(p_next!=NULL){
      p_next->Last=p_last;
    }

  }

}

